package com.yusong.algorithm.link;

/**
 给你一个链表，每 k 个节点一组进行翻转，请你返回翻转后的链表。

 k 是一个正整数，它的值小于或等于链表的长度。

 如果节点总数不是 k 的整数倍，那么请将最后剩余的节点保持原有顺序。
 */
public class ReverseKGroup25 {

    public static void main(String[] args) {
        int[] data = {1,2,3,4,5};
        ListNode node = ListNodeUtil.create(data);

        ReverseKGroup25 demo = new ReverseKGroup25();
        node = demo.reverseKGroup(node, 2);
        ListNodeUtil.printNode(node);
    }


    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode dummyHead = new ListNode(-1);
        dummyHead.next = head;
        preNode = dummyHead;
        tail = existTail(preNode, k);
        while(tail != null){
            reverseK(tail);
            tail = existTail(preNode, k);
        }
        return dummyHead.next;
    }

    public void reverseK(ListNode tail){
        ListNode curNode = preNode.next;
        ListNode nextNode = tail.next;
        preNode.next = tail;
        preNode = curNode;
        while(curNode != null &&  curNode != tail){
            tail.next = curNode;
            ListNode tmp = curNode.next;
            curNode.next = nextNode;
            nextNode = curNode;
            curNode = tmp;
        }

    }

    ListNode tail;
    ListNode preNode;

    /**
     后续的数据是否需要翻转
     **/
    private ListNode existTail(ListNode preNode,int k){
        if(preNode == null){
            return null;
        }
        int index = 1;
        while (index <= k){
            preNode = preNode.next;
            if(preNode == null){
                return null;
            }
            index++;
        }
        return preNode;
    }
}

/*
 示例：

 给你这个链表：1->2->3->4->5

 当 k = 2 时，应当返回: 2->1->4->3->5

 当 k = 3 时，应当返回: 3->2->1->4->5

  

 说明：

 你的算法只能使用常数的额外空间。
 你不能只是单纯的改变节点内部的值，而是需要实际进行节点交换。
 */